package be.kdg.bombermanunlimited.client.gui;

import java.awt.Image;
import java.awt.event.KeyEvent;

import be.kdg.bombermanunlimited.client.Interfaces.IProxyGuiPlayer;

/*
 * classe van een player, alle functies zijn zelfexplanatory
 * 
 * extra uitleg staat bij functies zelf
 */

public class GuiLocalPlayer {
	/*
	 * proxyrelated variables
	 */
	IProxyGuiPlayer proxy;
	private String name;
	private int bombRange;
	private boolean bombDropped;

	/*
	 * Related do drawing of GUI
	 */
	private int speed;
	private boolean dead;
	private int framecount;
	private int frameholdcount;
	SpriteSheet sheet;
	private int xOffset;
	private int yOffset;
	private int direction;
	private boolean canGoUp;
	private boolean canGoDown;
	private boolean canGoLeft;
	private boolean canGoRight;

	/*
	 * om te kijken hoe de speler can bewegen
	 */
	public boolean isCanGoUp() {
		return canGoUp;
	}

	public boolean isCanGoDown() {
		return canGoDown;
	}

	public boolean isCanGoLeft() {
		return canGoLeft;
	}

	public boolean isCanGoRight() {
		return canGoRight;
	}

	// lokaal kopieren via proxy
	public GuiLocalPlayer(IProxyGuiPlayer proxy) {
		this.name = proxy.getName();
		this.bombRange = proxy.getBombRange();
		if (proxy.isLocal()) {
			sheet = new SpriteSheet(5, 3, GUI_AbstractTile.TILE_HEIGHT,
					GUI_AbstractTile.TILE_WIDTH, "img/player.png");
		} else {
			sheet = new SpriteSheet(5, 3, GUI_AbstractTile.TILE_HEIGHT,
					GUI_AbstractTile.TILE_WIDTH, "img/oponent.png");
		}
		this.framecount = 0;
		this.frameholdcount = 0;
		this.direction = 0;
		this.dead = false;
		this.proxy = proxy;
		this.speed = 2;
		this.bombDropped = false;
		canGoUp = proxy.isCanGoUp();
		canGoDown = proxy.isCanGoDown();
		canGoLeft = proxy.isCanGoLeft();
		canGoRight = proxy.isCanGoRight();
		// System.out.print("Down:" + canGoDown + " Left:" + "" + canGoLeft
		// + " Right:" + canGoRight + " Up:" + canGoUp + " \n");
	}

	/*
	 * continuous movement: op de server is alles discreet, maar dit oogt niet
	 * mooi
	 * 
	 * hiervoor met extra offset variabelen toch continue beweging, maar
	 * discrete mapping.
	 * 
	 * Door out of sync met server na een paar bewegingen glitch het beeld soms,
	 * maar als de sync niet uitgevoerd wordt krijg je mapping fouten dus is
	 * (voorlopig) een beetje onontkomelijk
	 * 
	 * 
	 * 
	 * Het principe: offset op tile om te beweging, vanaf de speler voorbij een
	 * bepaalde treshold is, de discrete waarde ook aanpassen
	 */
	public synchronized void move(int dx, int dy) {
		int halfTileSize = GUI_AbstractTile.TILE_WIDTH / 2;

		if ((xOffset + dx > 0 && dx > 0) && (!canGoRight)) {
			// System.out.println("cant go right");
			dx = 0;
		}
		if ((xOffset + dx < 0 && dx < 0) && (!canGoLeft)) {
			// System.out.println("cant go left");
			dx = 0;
		}
		if ((yOffset + dy > 0 && dy > 0) && (!canGoDown)) {
			// System.out.println("cant go down");
			dy = 0;
		}
		if ((yOffset + dy < 0 && dy < 0) && (!canGoUp)) {
			// System.out.println("cant go up");
			dy = 0;
		}

		xOffset += dx;
		yOffset += dy;

		if ((dx != 0) || (dy != 0)) {
			incrementFrameCount();
		}

		if (xOffset > halfTileSize) {
			proxy.incColumn();
			this.canGoLeft = proxy.isCanGoLeft();
			this.canGoRight = proxy.isCanGoRight();
			this.canGoDown = proxy.isCanGoDown();
			this.canGoUp = proxy.isCanGoUp();

			xOffset = -halfTileSize + (xOffset - halfTileSize);
		} else if (xOffset < -halfTileSize) {
			proxy.decColumn();
			this.canGoLeft = proxy.isCanGoLeft();
			this.canGoRight = proxy.isCanGoRight();
			this.canGoDown = proxy.isCanGoDown();
			this.canGoUp = proxy.isCanGoUp();

			xOffset = halfTileSize + (xOffset + halfTileSize);
		}

		if (yOffset > halfTileSize) {
			proxy.incRow();
			this.canGoLeft = proxy.isCanGoLeft();
			this.canGoRight = proxy.isCanGoRight();
			this.canGoDown = proxy.isCanGoDown();
			this.canGoUp = proxy.isCanGoUp();

			yOffset = -halfTileSize + (yOffset - halfTileSize);
		} else if (yOffset < -halfTileSize) {
			proxy.decRow();
			this.canGoLeft = proxy.isCanGoLeft();
			this.canGoRight = proxy.isCanGoRight();
			this.canGoDown = proxy.isCanGoDown();
			this.canGoUp = proxy.isCanGoUp();

			yOffset = halfTileSize + (yOffset + halfTileSize);
		}
	}

	@SuppressWarnings("unused")
	// geeft de richting weer waar de speler naar kijkt. Dit is belangrijk voor
	// het laden van de sprites
	private void updateDirection(int dx, int dy) {
		if (dx > 0) {
			this.direction = 3;
		} else if (dx < 0) {
			this.direction = 1;
		}
		if (dy > 0) {
			this.direction = 0;
		} else if (dy < 0) {
			this.direction = 2;
		}

	}

	public int getX() {
		return GUI_AbstractTile.TILE_WIDTH * proxy.getColumn();
		// return GUI_AbstractTile.TILE_WIDTH * proxy.getColumn() + xOffset;
	}

	public int getY() {
		return GUI_AbstractTile.TILE_HEIGHT * proxy.getRow();
		// return GUI_AbstractTile.TILE_HEIGHT * proxy.getRow() + yOffset;
	}

	public Image getPlayerSprite() {
		if (!dead) {
			return sheet.getSprite(direction * 3 + framecount);
		} else {
			xOffset = 0;
			yOffset = 0;
			return sheet.getSprite(12);
		}
	}

	// voor de wandelanimaties switchen tussen 3 sprites om zo 
	//een illusie van beweging te creeeren
	public void incrementFrameCount() {
		frameholdcount++;
		if (frameholdcount >= 9) {
			framecount++;
			if (framecount > 2) {
				framecount = 0;
			}
			frameholdcount = 0;
		}

	}

	public void forceDirection(int direction) {
		this.direction = direction;
	}

	
	//gaat afhandelen met server wat er moet gedaan worden
	//bij beweging/indrukken toetsen
	public void keyPressed(KeyEvent e) {
		if (!dead) {
			int dx = 0, dy = 0;

			int key = e.getKeyCode();

			if (key == KeyEvent.VK_LEFT) {
				forceDirection(1);
				dx = -this.speed;
			}

			if (key == KeyEvent.VK_RIGHT) {
				forceDirection(3);
				dx = this.speed;
			}

			if (key == KeyEvent.VK_UP) {
				forceDirection(2);
				dy = -this.speed;
			}

			if (key == KeyEvent.VK_DOWN) {
				forceDirection(0);

				dy = this.speed;
			}

			if (key == KeyEvent.VK_SPACE && !bombDropped) {
				dropBomb();
				bombDropped = true;
			}

			move(dx, dy);
		}
	}

	public String getName() {
		return name;
	}

	public int getBombRange() {
		return bombRange;
	}

	public void keyReleased(KeyEvent e) {
		if (!dead) {
			framecount = 1;
			int dx = 0, dy = 0;
			if (e.getKeyCode() == KeyEvent.VK_SPACE) {
				bombDropped = false;
			}

			move(dx, dy);
		}

	}

	public void dropBomb() {
		proxy.dropBomb();
	}

	public void setLocation(int row, int column) {
		proxy.setLocation(row, column);
	}

	public void setDead() {
		this.dead = true;
	}

	public boolean isDead() {
		return this.dead;
	}
}
